package cn.tedu.charging.order.service;

import cn.tedu.charging.common.pojo.entity.ProgressEntity;
import cn.tedu.charging.common.pojo.message.ChargingCheckResultMessage;
import cn.tedu.charging.common.pojo.message.ChargingProgressMsg;
import cn.tedu.charging.common.pojo.message.DelayCheckMessage;
import cn.tedu.charging.common.pojo.message.ProgressData;
import cn.tedu.charging.common.pojo.param.ProgressCostParam;
import cn.tedu.charging.common.pojo.po.ChargingBillFailPO;
import cn.tedu.charging.common.pojo.po.ChargingBillSuccessPO;
import cn.tedu.charging.common.pojo.vo.ProgressCostVO;
import cn.tedu.charging.common.protocol.WebSocketMessage;
import cn.tedu.charging.common.utils.SnowflakeIdGenerator;
import cn.tedu.charging.order.feign.CostClient;
import cn.tedu.charging.order.repository.FailBillRepository;
import cn.tedu.charging.order.repository.ProgressEsRepository;
import cn.tedu.charging.order.repository.SuccessBillRepository;
import cn.tedu.charging.order.websocket.WebSocketServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;

@Service
@Slf4j
public class OrderConsumerServiceImpl implements OrderConsumerService{
    @Autowired
    private SuccessBillRepository successBillRepository;
    @Autowired
    private FailBillRepository failBillRepository;
    @Autowired
    private WebSocketServer webSocketServer;
    @Override
    public void handleCheckResult(ChargingCheckResultMessage msg) {
        //1.利用msg中orderNo(bill_id) 读取success表格和fail表中是否存在数据 判断本次是否可增
        log.debug("检查充电结果入参:{}",msg);
        String billId=msg.getOrderNo();
        boolean exists=checkExists(billId);
        //2.判断是否可增 继续 根据msg中result true-success false-fail
        if (exists){
            log.debug("订单已存在:{}",billId);
            return;
        }else{
            log.debug("订单不存在:{}",billId);
            //根据msg中result结果封装不同数据 successPO failPO
            Boolean result = msg.getResult();
            if (result){
                log.debug("自检反馈结果是成功,新增success");
                //组织一个ChargingBillSuccessPO
                saveSuccess(msg);
                //TODO 开始充电把
            }else{
                log.debug("自检反馈结果是失败,新增fail");
                //组织一个ChargingBillFailPO
                saveFail(msg.getOrderNo(),msg.getUserId(),new Date());
                //给用户发送一个消息告知前端 当前扫码下单失败 重新换枪 考虑用户体验 赠送一张优惠券[短链接]
                WebSocketMessage<String> message = new WebSocketMessage<>();
                message.setState(1);
                message.setData("A对不起 扫码下单失败,请还枪,给您赠送一张优惠券http://com.charging/D9FH213");
                webSocketServer.pushMessage(message,msg.getUserId());
                log.debug("发送消息给用户:{}",message);
            }
        }
    }

    @Override
    public void handleDelayResult(DelayCheckMessage msg) {
        //1.利用参数中 orderNo 读取成功或者失败 [复用]
        String billId = msg.getOrderNo();
        boolean exists = checkExists(billId);
        //2.如果成功了或者失败了 什么都不做结束
        if (exists){
            log.debug("延迟消息订单编号:{},设备有响应,已经生成了订单");
            return;
        }else{
            //3.如果没有成功页没有失败 按失败处理 [复用]
            log.debug("延迟消息订单编号:{},设备没有响应,开始处理失败");
            saveFail(msg.getOrderNo(),msg.getUserId(),new Date());
        }

    }
    @Autowired
    private CostClient costClient;
    @Autowired
    private ProgressEsRepository progressEsRepository;
    private SnowflakeIdGenerator snowflakeIdGenerator=new SnowflakeIdGenerator();
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Override
    public void handleChargingProgress(ChargingProgressMsg msg) {
        //1.利用参数 orderNo userId stationId gunId pileId capacity 调用计价获取累计金额
        ProgressCostParam param=new ProgressCostParam();
        BeanUtils.copyProperties(msg,param);
        ProgressCostVO vo = costClient.calculateCost(param).getData();
        //2.组织本次充电记录es的po对象 写入es 保存历史充电日志
        ProgressEntity entity=new ProgressEntity();
        BeanUtils.copyProperties(msg,entity);
        //补充2个属性 id 和totalCost
        entity.setId(snowflakeIdGenerator.nextId()+"");
        entity.setTotalCost(vo.getTotalCost());
        progressEsRepository.save(entity);
        //3根据设备同步的信息属性isFull 判断是否充电完成
        Boolean isFull = msg.getIsFull();
        if (isFull){
            //TODO 提示信息 冲完了 但是前端没有接收这类数据 模拟只能使用 错误信息state=1
            WebSocketMessage<String> message = new WebSocketMessage<>();
            message.setState(1);
            message.setData("A充电完成,请取枪支付,欢迎下次光临");
            webSocketServer.pushMessage(message,msg.getUserId());
        }else{
            //充电中的进度,同步给小程序
            WebSocketMessage<ProgressData> message = new WebSocketMessage<>();
            //state=3 前端才会展示同步进度数据
            message.setState(3);
            ProgressData data=new ProgressData();
            String capacityKey="charging:capacity:total:"+msg.getOrderNo();

            //单次度数
            data.setChargingCapacity(redisTemplate.boundValueOps(capacityKey).increment(msg.getChargingCapacity()));
            data.setTotalCost(vo.getTotalCost());
            data.setOneElectricityCost(vo.getPowerFee());
            //当前消息 没有计算时间 依据 补充测试数据
            data.setHours(0);
            data.setMinutes(10);
            data.setSeconds(10);
            data.setTotalCapacity(100.00);//预估充满的总电度数
            message.setData(data);
            webSocketServer.pushMessage(message,msg.getUserId());
        }
    }

    private void saveFail(String orderNo,Integer userId,Date updateTime) {
        ChargingBillFailPO po=new ChargingBillFailPO();
        po.setBillId(orderNo);
        po.setUserId(userId);
        po.setCreateTime(updateTime);
        po.setUpdateTime(updateTime);
        failBillRepository.save(po);
    }

    private void saveSuccess(ChargingCheckResultMessage msg) {
        ChargingBillSuccessPO po=new ChargingBillSuccessPO();
        //只补充核心的 能补充的
        po.setBillId(msg.getOrderNo());
        po.setUserId(msg.getUserId());
        //创建时间 修改时间
        po.setCreateTime(new Date());
        po.setUpdateTime(new Date());
        //初始化状态值 正在充电
        po.setBillStatus(1);
        successBillRepository.save(po);
    }

    private boolean checkExists(String billId) {
        //select count(0) from charging_bill_success where bill_id=billId
        Long countSuccess=successBillRepository.countByBillId(billId);
        //select count(0) from charging_bill_fail where bill_id=billId
        Long countFail=failBillRepository.countByBillId(billId);
        return countSuccess>0||countFail>0;
    }
}
